﻿using System;
using System.Collections.Generic;
using System.Data.Services.Client;
using System.Linq;
using Microsoft.Samples.ServiceHosting.StorageClient;
using Microsoft.ServiceHosting.ServiceRuntime;
using System.Collections.ObjectModel;



namespace ZeCloud.TekFriends.Metier.Table
{
    public class TekFriendsService : TableStorageDataServiceContext
    {
       
        public TekFriendsService(StorageAccountInfo accountInfo, RetryPolicy in_policy)
            : base(accountInfo)
        {
            RetryPolicy = in_policy;
        }

        public IQueryable<Personne> Personnes
        {
            get
            {
                return this.CreateQuery<Personne>("Personnes");
            }
        }

              public IQueryable<Reseau> Reseaux
        {
            get
            {
                return this.CreateQuery<Reseau>("Reseaux");
            }
        }

  

        public Personne CreerPersonne(string in_email, string in_liveid, string in_ville, string in_nom, string in_prenom)
        {
            
            //// Attention à ce que la ville ne contienne pas de _ !
            //if (in_ville.Contains("_"))
            //{
            //    RoleManager.WriteToLog("Information", "RestoService, CreerRestoPar : La ville ne peut pas contenir de _");
            //    return null;
            //}

            try
            {
                var l_created = new Personne(in_email) { nom = in_nom, liveID = in_liveid, prenom = in_prenom, ville = in_ville } ;
                this.AddObject("Personnes", l_created);
                this.SaveChanges();

                return l_created;
            }
            catch (DataServiceRequestException)
            {
                //var log = log4net.LogManager.GetLogger(this.GetType());
                //log.Debug("AnniversaireService, CreerAnniversaire : Entry already exists !");
                RoleManager.WriteToLog("Information", "TekFriendsService, CreerPersonne : Entry already exists !");

                return null;
            }
            catch (InvalidOperationException)
            {
                // Pb d'implementation, on réutilise un contexte existant
                //var log = log4net.LogManager.GetLogger("Metier.AnniversaireService");
                //log.Debug("AnniversaireService, CreerAnniversaire : Pb d'implémentation !");
                RoleManager.WriteToLog("Information", "TekFriendsService, CreerPersonne : Pb d'implémentation !");

                return null;
            }
        }

            public bool CreerReseau(string in_email1, string in_email2) {
                //TODO Passer par une queue de message, cf specs
                //TODO Mettre en place le workflow
                var l_sens1 = new Reseau(in_email1, in_email2, Reseau.ACCEPTE);
                this.AddObject("Reseaux", l_sens1);
                this.SaveChanges();

                var l_sens2 = new Reseau(in_email2, in_email1, Reseau.ACCEPTE);
                this.AddObject("Reseaux", l_sens2);
                this.SaveChanges();

                return true;

            }


            public bool ValiderReseau(string in_email1, string in_email2) {
                // Etat = Refuse
                return true;

            }

            public bool RefuserReseau(string in_email1, string in_email2) {
                // Etat = Accepté
                return true;

            }

    
    
        /** Retourne la liste des restos dans la ville spécifiée
         */
        public IEnumerable<string> RechercherEntourage(string in_email1)
        {
            //TODO vérifier & versus &&

            //TODO mettre en place du cache

            var results = (from r in Reseaux
                          where (r.PartitionKey == in_email1)
                          & (r.status == Reseau.ACCEPTE)
                          select r.RowKey);

            return results;
        }

        ///** Retourne les villes commençant par
        // */
        //public string[] RechercherVillesDemarrantPar(string in_villePrefix)
        //{
        //    var results = (from r in Restos
        //                  where (r.PartitionKey.CompareTo(StringHelper.RemoveAccentuation(in_villePrefix)) >= 0)
        //                  & (r.PartitionKey.CompareTo(StringHelper.RemoveAccentuation(in_villePrefix) + "{") < 0)
        //                  select r) as IEnumerable<Resto>;

        //    var villes = (from v in results
        //                  orderby v.ville ascending
        //                  select v.ville).Distinct();

        //    return villes.ToArray();
        //}

        ///** Retourne le premier resto dans la ville spécifié s'il existe, sinon retoure null
        // */
        //public Resto GetRestoParNomEtVille(string in_nom, string in_ville)
        //{
        //    try
        //    {
        //        // StartWith is not supported => replace with a string comparison
        //        //var result = (from r in Restos
        //        //             where r.PartitionKey.StartsWith(StringHelper.RemoveAccentuation(in_ville)+"_") 
        //        //             select r) as IEnumerable<Resto>;

        //        // Retreive all the restaurants for a given town
        //        // Query PartitionKey : >= ville_0 and < ville_(character after 9 == ':')
        //        var result = (from r in Restos
        //                      where (r.PartitionKey.CompareTo(StringHelper.RemoveAccentuation(in_ville) + "_0") >= 0)
        //                      & (r.PartitionKey.CompareTo(StringHelper.RemoveAccentuation(in_ville) + "_:") < 0)
        //                      select r) as IEnumerable<Resto>;

        //        // Filter in_memory (because azure would not support the concatened query)
        //        var filtered = from s in result
        //                       where StringHelper.RemoveAccentuation(s.nom).Equals(StringHelper.RemoveAccentuation(in_nom))
        //                       select s;

        //        return filtered.FirstOrDefault();
        //    }
        //    catch (InvalidOperationException)
        //    {
        //        RoleManager.WriteToLog("Information", "RestoService, GetRestoParNomEtVille : Pas de restaurant nommé " + in_nom + " pour la ville " + in_ville);
        //        return null;
        //    }
        //}

        ///** Retourne tous les restos dans la ville spécifiée, et null si pas de restos
        // */
        //public IEnumerable<Resto> GetRestosParNomEtVille(string in_nom, string in_ville)
        //{
        //    try
        //    {
        //        // Retreive all the restaurants for a given town
        //        // Query PartitionKey : >= ville_0 and < ville_(character after 9 == ':')
        //        var result = (from r in Restos
        //                      where (r.PartitionKey.CompareTo(StringHelper.RemoveAccentuation(in_ville) + "_0") >= 0)
        //                      & (r.PartitionKey.CompareTo(StringHelper.RemoveAccentuation(in_ville) + "_:") < 0)
        //                      select r) as IEnumerable<Resto>;

        //        // Filter in_memory (because azure would not support the concatened query)
        //        var filtered = from s in result
        //                       where StringHelper.RemoveAccentuation(s.nom).Equals(StringHelper.RemoveAccentuation(in_nom))
        //                       select s;

        //        return result;
        //    }
        //    catch (InvalidOperationException)
        //    {
        //        RoleManager.WriteToLog("Information", "RestoService, GetRestoParNomEtVille : Pas de restaurant nommé " + in_nom + " pour la ville " + in_ville);
        //        return null;
        //    }
        //}

        //public Resto GetRestoByUniqueId(string in_uniqueID)
        //{
        //    // [PENDING] Attention si on change la clé de partitionnement, la requête ne fonctionnera plus
        //    // Mais je ne veux pas utiliser l'unique id pour des raisons de perfs
        //    var result = (from r in Restos
        //                 where r.PartitionKey.Equals(Resto.ExtractPartitionKeyFromRestoUniqueId(in_uniqueID))
        //                 & r.RowKey.Equals(Resto.ExtractRowKeyFromRestoUniqueId(in_uniqueID))
        //                 select r) as IEnumerable<Resto>;

        //    // [QUALITE] Si on en trouve plusieurs, c'est qu'on a un pb de qualité dans le SGBDR
        //    switch (result.Count())
        //    {
        //        case 0: return null;
        //        case 1: return result.FirstOrDefault();
        //        default :
        //            RoleManager.WriteToLog("Warning", "RestoService, GetRestoByUniqueId : Several restaurants with same unique id " + in_uniqueID);
        //            return result.FirstOrDefault();
        //    }
        //}

        ///**
        // */
        //public Element CreerElement(string in_restoId, string in_element, string in_categorie, string in_description)
        //{

        //    try
        //    {
        //        var l_created = new Element(in_restoId, in_element, ANONYMOUS, in_categorie, in_description);
        //        this.AddObject("Elements", l_created);
        //        this.SaveChanges();
        //        return l_created;
        //    }
        //    catch (DataServiceRequestException dsre)
        //    {
        //        //var log = log4net.LogManager.GetLogger(this.GetType());
        //        //log.Debug("AnniversaireService, CreerAnniversaire : Entry already exists !");
        //        RoleManager.WriteToLog("Information", "RestoService, CreerElement : Entry already exists !");

        //        return null;
        //    }
        //    catch (InvalidOperationException ioe)
        //    {
        //        // Pb d'implementation, on réutilise un contexte existant
        //        //var log = log4net.LogManager.GetLogger("Metier.AnniversaireService");
        //        //log.Debug("AnniversaireService, CreerAnniversaire : Pb d'implémentation !");
        //        RoleManager.WriteToLog("Information", "RestoService, CreerElement : Pb d'implémentation !");

        //        return null;
        //    }
        //}

        //// STEVE : je ne comprends pas à quoi sert cette méthode, elle devrait retourner une liste
        //public Element GetElementParNomEtResto(string in_restoUniqueId, string elementName)
        //{
        //    var result = from e in Elements
        //                 where (e.PartitionKey == in_restoUniqueId) &
        //                 (e.Title == elementName)
        //                 select e;

        //    return result == null ? null : ProcessElementQuery(result).FirstOrDefault();
        //}

        ///// <summary>
        ///// Retourne la liste des restos qui commencent par la ville demandée
        ///// </summary>
        ///// <param name="in_restoId"></param>
        ///// <returns></returns>
        //public IEnumerable<Element> RechercherElementsPourResto(string in_restoId)
        //{
        //    var found = from e in Elements
        //                where (e.PartitionKey == in_restoId)
        //                select e;

        //    return found;
        //}

  

        //public void SupprimerResto(Resto resto)
        //{
        //    // [PENDING] Faire le nettoyage de façon asynchrone
        //    //foreach (Element element in RechercherElementsPourResto(resto.uniqueId))
        //    //{
        //    //    this.SupprimerElement(element);
        //    //}
        //    this.AttachTo("Restos", resto, "*");
        //    this.DeleteObject(resto);
        //    this.SaveChanges();
        //}

        ///// <summary>
        ///// Supprime un element et tous ses prix associés
        ///// </summary>
        ///// <param name="element">L'element a supprime</param>
        //public void SupprimerElement(Element element)
        //{
        //    // [PENDING] Faire le nettoyage de façon asynchrone
        //    //foreach (DetailPrix prix in RechercherPrixPourElement(element.UniqueId))
        //    //{
        //    //    this.SupprimerDetailPrix(prix);
        //    //}

        //    this.AttachTo("Elements", element, "*");
        //    this.DeleteObject(element);
        //    this.SaveChanges();
        //}

        ////public IEnumerable<Resto> ProcessRestoQuery(IQueryable<Resto> resultset)
        ////{
        ////    TableStorageDataServiceQuery<Resto> query = new TableStorageDataServiceQuery<Resto>(resultset as DataServiceQuery<Resto>);
        ////    IEnumerable<Resto> queryResults = query.ExecuteAllWithRetries();
        ////    return queryResults;
        ////}

        //public IEnumerable<Element> ProcessElementQuery(IQueryable<Element> resultset)
        //{
        //    TableStorageDataServiceQuery<Element> query = new TableStorageDataServiceQuery<Element>(resultset as DataServiceQuery<Element>);
        //    IEnumerable<Element> queryResults = query.ExecuteAllWithRetries();
        //    return queryResults;
        //}

        ////public IEnumerable<string> ProcessStringQuery(IQueryable<string> resultset)
        ////{
        ////    TableStorageDataServiceQuery<string> query = new TableStorageDataServiceQuery<string>(resultset as DataServiceQuery<string>);
        ////    IEnumerable<string> queryResults = query.ExecuteAllWithRetries();
        ////    return queryResults;
        ////}

        //private void CreerEchantillons(Resto r)
        //{
        //    CreerElement(r.uniqueId, "Menu enfant", "Menu", "Menu pour les enfants");
        //    CreerElement(r.uniqueId, "Menu midi entree plat ou plat dessert", "Menu", "Menu midi leger comprenant entree plat ou plat dessert");
        //    CreerElement(r.uniqueId, "Menu midi entre plat dessert", "Menu", "Menu midi comprenant entree plat et dessert");
        //    CreerElement(r.uniqueId, "Plat du jour 1", "Plat du jour", "Plat du jour d'un certain montant");
        //    CreerElement(r.uniqueId, "Plat du jour 2", "Plat du jour", "Plat du jour d'un certain autre montant");
        //    CreerElement(r.uniqueId, "Coca-cola", "Boisson", "Coca cola en bouteille 33cl");
        //    CreerElement(r.uniqueId, "Cafe expresso", "Boisson", "Cafe expresso");
        //}

    }
}
